/**
 * Some “list” response that can be paginated have a different response structure
 *
 * They have a `total_count` key in the response (search also has `incomplete_results`,
 * /installation/repositories also has `repository_selection`), as well as a key with
 * the list of the items which name varies from endpoint to endpoint:
 *
 * - https://developer.github.com/v3/search/#example (key `items`)
 * - https://developer.github.com/v3/checks/runs/#response-3 (key: `check_runs`)
 * - https://developer.github.com/v3/checks/suites/#response-1 (key: `check_suites`)
 * - https://developer.github.com/v3/apps/installations/#list-repositories (key: `repositories`)
 *
 * Octokit normalizes these responses so that paginated results are always returned following
 * the same structure. One challenge is that if the list response has only one page, no Link
 * header is provided, so this header alone is not sufficient to check wether a response is
 * paginated or not. For the exceptions with the namespace, a fallback check for the route
 * paths has to be added in order to normalize the response. We cannot check for the total_count
 * property because it also exists in the response of Get the combined status for a specific ref.
 */

module.exports = normalizePaginatedListResponse

const Deprecation = require('deprecation')
const once = require('once')

const deprecateIncompleteResults = once((log, deprecation) => log.warn(deprecation))
const deprecateTotalCount = once((log, deprecation) => log.warn(deprecation))
const deprecateNamespace = once((log, deprecation) => log.warn(deprecation))

const REGEX_IS_SEARCH_PATH = /^\/search\//
const REGEX_IS_CHECKS_PATH = /^\/repos\/[^/]+\/[^/]+\/commits\/[^/]+\/(check-runs|check-suites)/
const REGEX_IS_INSTALLATION_REPOSITORIES_PATH = /^\/installation\/repositories/

function normalizePaginatedListResponse (octokit, url, response) {
  const path = url.replace(octokit.request.endpoint.DEFAULTS.baseUrl, '')
  if (
    !REGEX_IS_SEARCH_PATH.test(path) &&
    !REGEX_IS_CHECKS_PATH.test(path) &&
    !REGEX_IS_INSTALLATION_REPOSITORIES_PATH.test(path)
  ) {
    return
  }

  // keep the additional properties intact to avoid a breaking change,
  // but log a deprecation warning when accessed
  const incompleteResults = response.data.incomplete_results
  const repositorySelection = response.data.repository_selection
  const totalCount = response.data.total_count
  delete response.data.incomplete_results
  delete response.data.repository_selection
  delete response.data.total_count

  const namespaceKey = Object.keys(response.data)[0]

  response.data = response.data[namespaceKey]

  Object.defineProperty(response.data, namespaceKey, {
    get () {
      deprecateNamespace(octokit.log, new Deprecation(`[@octokit/rest] "result.data.${namespaceKey}" is deprecated. Use "result.data" instead`))
      return response.data
    }
  })

  if (typeof incompleteResults !== 'undefined') {
    Object.defineProperty(response.data, 'incomplete_results', {
      get () {
        deprecateIncompleteResults(octokit.log, new Deprecation('[@octokit/rest] "result.data.incomplete_results" is deprecated.'))
        return incompleteResults
      }
    })
  }

  if (typeof repositorySelection !== 'undefined') {
    Object.defineProperty(response.data, 'repository_selection', {
      get () {
        deprecateTotalCount(octokit.log, new Deprecation('[@octokit/rest] "result.data.repository_selection" is deprecated.'))
        return repositorySelection
      }
    })
  }

  Object.defineProperty(response.data, 'total_count', {
    get () {
      deprecateTotalCount(octokit.log, new Deprecation('[@octokit/rest] "result.data.total_count" is deprecated.'))
      return totalCount
    }
  })
}
